<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring Session 分布式会话解决方案</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .code-block {
            background: #1e1e1e;
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        }
        .feature-card {
            transition: all 0.3s ease;
            backdrop-filter: blur(10px);
            background: rgba(255,255,255,0.9);
        }
        .feature-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
        }
        .section-title::before {
            content: '';
            position: absolute;
            left: -20px;
            top: 50%;
            transform: translateY(-50%);
            width: 4px;
            height: 30px;
            background: linear-gradient(to bottom, #667eea, #764ba2);
        }
        .mermaid {
            display: flex;
            justify-content: center;
            margin: 2rem 0;
        }
        .image-container {
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0,0,0,0.1);
            transition: all 0.3s ease;
        }
        .image-container:hover {
            transform: scale(1.02);
            box-shadow: 0 15px 40px rgba(0,0,0,0.15);
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-6">
        <div class="max-w-6xl mx-auto">
            <div class="text-center">
                <h1 class="text-5xl md:text-6xl font-bold mb-6 tracking-tight">
                    Spring Session
                </h1>
                <p class="text-xl md:text-2xl mb-8 opacity-90">
                    优雅解决分布式系统中的会话共享难题
                </p>
                <div class="flex justify-center space-x-6 text-lg">
                    <div class="flex items-center">
                        <i class="fas fa-server mr-2"></i>
                        <span>分布式存储</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-sync-alt mr-2"></i>
                        <span>无缝集成</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-shield-alt mr-2"></i>
                        <span>高可用性</span>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="max-w-6xl mx-auto px-6 py-12">
        <!-- Introduction -->
        <section class="mb-16">
            <div class="bg-white rounded-2xl shadow-lg p-8 md:p-12">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 relative pl-6 section-title">
                    核心概念
                </h2>
                <p class="text-lg text-gray-700 leading-relaxed mb-8">
                    Spring Session 提供了一个优雅的解决方案，将传统的 HTTP Session 存储从应用服务器内存转移到外部存储系统（如 Redis），
                    从而实现了真正的分布式会话管理。这种方式不仅解决了集群环境下的会话共享问题，还提供了更好的可扩展性和容错能力。
                </p>
                
                <!-- Architecture Diagram -->
                <div class="my-12">
                    <div class="mermaid">
                        graph TB
                            A[客户端请求] --> B[SessionRepositoryFilter]
                            B --> C[包装 Request/Response]
                            C --> D[Controller 处理]
                            D --> E[SessionRepository]
                            E --> F[Redis 存储]
                            
                            style A fill:#667eea,stroke:#fff,stroke-width:2px,color:#fff
                            style B fill:#764ba2,stroke:#fff,stroke-width:2px,color:#fff
                            style C fill:#8b5cf6,stroke:#fff,stroke-width:2px,color:#fff
                            style D fill:#a78bfa,stroke:#fff,stroke-width:2px,color:#fff
                            style E fill:#c4b5fd,stroke:#333,stroke-width:2px
                            style F fill:#e9d5ff,stroke:#333,stroke-width:2px
                    </div>
                </div>
            </div>
        </section>

        <!-- Core Interface -->
        <section class="mb-16">
            <div class="bg-white rounded-2xl shadow-lg p-8 md:p-12">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 relative pl-6 section-title">
                    核心接口设计
                </h2>
                <p class="text-lg text-gray-700 mb-8">
                    SessionRepository 是 Spring Session 的核心接口，定义了会话管理的基本操作：
                </p>
                
                <div class="code-block p-6 overflow-x-auto">
                    <pre class="text-gray-300"><code class="language-java"><span class="text-purple-400">public interface</span> <span class="text-yellow-300">SessionRepository</span>&lt;<span class="text-blue-300">S</span> <span class="text-purple-400">extends</span> <span class="text-yellow-300">Session</span>&gt; {
    <span class="text-blue-300">S</span> <span class="text-green-300">createSession</span>();
    
    <span class="text-purple-400">void</span> <span class="text-green-300">save</span>(<span class="text-blue-300">S</span> var1);
    
    <span class="text-blue-300">S</span> <span class="text-green-300">findById</span>(<span class="text-yellow-300">String</span> var1);
    
    <span class="text-purple-400">void</span> <span class="text-green-300">deleteById</span>(<span class="text-yellow-300">String</span> var1);
}</code></pre>
                </div>
                
                <div class="grid md:grid-cols-2 gap-6 mt-8">
                    <div class="feature-card p-6 rounded-xl border border-gray-200">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-plus-circle text-3xl text-purple-600 mr-4"></i>
                            <h3 class="text-xl font-semibold">创建会话</h3>
                        </div>
                        <p class="text-gray-600">createSession() 方法用于创建新的会话实例，自动生成唯一的会话标识符。</p>
                    </div>
                    
                    <div class="feature-card p-6 rounded-xl border border-gray-200">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-save text-3xl text-purple-600 mr-4"></i>
                            <h3 class="text-xl font-semibold">保存会话</h3>
                        </div>
                        <p class="text-gray-600">save() 方法将会话数据持久化到外部存储，确保数据的一致性和可靠性。</p>
                    </div>
                    
                    <div class="feature-card p-6 rounded-xl border border-gray-200">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-search text-3xl text-purple-600 mr-4"></i>
                            <h3 class="text-xl font-semibold">查找会话</h3>
                        </div>
                        <p class="text-gray-600">findById() 方法根据会话ID从存储中检索会话数据，支持快速访问。</p>
                    </div>
                    
                    <div class="feature-card p-6 rounded-xl border border-gray-200">
                        <div class="flex items-center mb-4">
                            <i class="fas fa-trash-alt text-3xl text-purple-600 mr-4"></i>
                            <h3 class="text-xl font-semibold">删除会话</h3>
                        </div>
                        <p class="text-gray-600">deleteById() 方法用于清理过期或无效的会话，释放存储空间。</p>
                    </div>
                </div>
            </div>
        </section>

        <!-- Working Principle -->
        <section class="mb-16">
            <div class="bg-white rounded-2xl shadow-lg p-8 md:p-12">
                <h2 class="text-3xl font-bold mb-6 text-gray-800 relative pl-6 section-title">
                    工作原理详解
                </h2>
                
                <div class="space-y-8">
                    <div>
                        <h3 class="text-2xl font-semibold mb-4 flex items-center">
                            <i class="fas fa-filter text-purple-600 mr-3"></i>
                            请求拦截机制
                        </h3>
                        <p class="text-lg text-gray-700 mb-6">
                            SessionRepositoryFilter 是整个 Spring Session 的入口点。它负责拦截所有的 HTTP 请求，
                            并将原生的 HttpServletRequest 和 HttpServletResponse 包装成 SessionRepositoryRequestWrapper 
                            和 SessionRepositoryResponseWrapper。
                        </p>
                        <div class="image-container">
                            <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1660616265260-f3a32887-e897-4cbb-bf4b-530cbacdb18f.png" 
                                 alt="Spring Session 架构图" 
                                 class="w-full">
                        </div>
                    </div>
                    
                    <div>
                        <h3 class="text-2xl font-semibold mb-4 flex items-center">
                            <i class="fas fa-exchange-alt text-purple-600 mr-3"></i>
                            请求包装过程
                        </h3>
                        <p class="text-lg text-gray-700 mb-6">
                            通过包装器模式，Spring Session 实现了对原生 Servlet API 的透明替换。
                            当 Controller 调用 request.getSession() 时，实际上调用的是包装器中的方法，
                            该方法会从 Redis 中获取或创建会话。
                        </p>
                        <div class="grid md:grid-cols-2 gap-6">
                            <div class="image-container">
                                <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1637283356737-d906eb2c-e6f6-4b01-bb2c-215bf0dc13dd.png" 
                                     alt="SessionRepositoryFilter 工作流程" 
                                     class="w-full">
                            </div>
                            <div class="image-container">
                                <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1637283589830-85345ad1-84f6-45df-8425-6c54f1a8ef02.png" 
                                     alt="请求包装细节" 
                                     class="w-full">
                            </div>
                        </div>
                    </div>
                    
                    <div>
                        <h3 class="text-2xl font-semibold mb-4 flex items-center">
                            <i class="fas fa-cogs text-purple-600 mr-3"></i>
                            完整执行流程
                        </h3>
                        <div class="image-container mb-6">
                            <img src="https://cdn.nlark.com/yuque/0/2021/png/21449790/1637283687811-df16a7dc-09a1-47ee-83d3-435b902e054a.png" 
                                 alt="Spring Session 完整执行流程" 
                                 class="w-full">
                        </div>
                        
                        <div class="mermaid">
                            sequenceDiagram
                                participant C as 客户端
                                participant F as SessionRepositoryFilter
                                participant W as RequestWrapper
                                participant A as Controller
                                participant R as Redis
                                
                                C->>F: HTTP 请求
                                F->>W: 创建包装器
                                W->>A: 传递包装后的请求
                                A->>W: getSession()
                                W->>R: 查询/创建会话
                                R-->>W: 返回会话数据
                                W-->>A: 返回 Session
                                A->>C: HTTP 响应
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Benefits -->
        <section class="mb-16">
            <div class="bg-gradient-to-r from-purple-600 to-indigo-600 rounded-2xl shadow-lg p-8 md:p-12 text-white">
                <h2 class="text-3xl font-bold mb-8 text-center">为什么选择 Spring Session？</h2>
                
                <div class="grid md:grid-cols-3 gap-8">
                    <div class="text-center">
                        <i class="fas fa-rocket text